package nespresso.beans;

import java.sql.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Base {
        public Connection cnx;
        private String cnxString;
        private String cnxUser;
        private String cnxPass;
        
        private ResultSet res;
        private Log log; 
        
        public Base() {
                log = LogFactory.getLog(Base.class);
                cnxString = "jdbc:mysql://localhost/NESPRESSO";
                cnxUser   = "NESPRESSO";
                cnxPass   = "NESPRESSO";
                
                try {
                        Class.forName("com.mysql.jdbc.Driver");
                        cnx = DriverManager.getConnection(cnxString, cnxUser, cnxPass);
                        log.info("Connexion à la base de données.");
                        
                } catch (Exception e){
                        log.error("echec pilote Mysql : "+e);
                }

        }
        
        public void GetResultat(String table, String champ, String id) {
                String req = "SELECT * FROM " + table;
                if(champ != "") req = req + " WHERE "+ champ + "='" + id + "'";
                try {
                        Statement s = cnx.createStatement();
                        res = s.executeQuery(req);
                        log.info("Requête exécutée : " + req);
                } catch(Exception e) {
                        System.out.println("echec pilote Mysql : "+e);
                }
        }
        
        public void GetResultat(String table, String[] champ, String[] id) {
                String req = "SELECT * FROM " + table;
                int nbchamp = champ.length;
                int nbid    = id.length;
                if(nbid < nbchamp) {
                        log.error("Le nombre de valeurs plus petit que le nombre de champs !");
                        res = null;
                }
                for(int i=0; i<nbchamp;i++) 
                        if(i==0) req = req + " WHERE "+ champ[i] + "='" + id[i] + "'";
                        else req = req + " AND "+ champ[i] + "='" + id[i] + "'";
                try {
                        Statement s = cnx.createStatement();
                        res = s.executeQuery(req);
                        log.info("Requête exécutée : " + req);
                } catch(Exception e) {
                        System.out.println("echec pilote Mysql : "+e);
                }
        }
        
        public void GetResultat(String table) {
                GetResultat(table, "", "");
        }
        
        public void ExecuteRequete(String req) {
                try {
                        Statement s = cnx.createStatement();
                        res = s.executeQuery(req);
                        log.info("Requête exécutée : " + req);
                } catch(Exception e) {
                        System.out.println("echec pilote Mysql : "+e);
                }
        }
        
        public boolean Suivant() {
                boolean retour = false;
                try {
                        retour = res.next();
                } catch(Exception e) {
                        log.error("Erreur lors de la recherche de l'élément suivant : " + e);
                }
                return retour;
        }
        
        public String GetTexte(String champ) {
                String v = new String();
                try {
                        v = res.getString(champ);
                } catch(Exception e) {
                        log.error("Erreur lors de la récupération de " + champ + " : " + e);
                }
        return v;
        }
        
        public float GetReel(String champ) {
                float v = 0;
                try {
                        v = res.getFloat(champ);
                } catch(Exception e) {
                        log.error("Erreur lors de la récupération de " + champ + " : " + e);
                }
                return v;
        }
        
        public int GetEntier(String champ) {
                int v = 0;
                try {
                        v = res.getInt(champ);
                } catch(Exception e) {
                        log.error("Erreur lors de la récupération de " + champ + " : " + e);
                }
                return v;
        }
        
        public boolean GetBoolean(String champ) {
                boolean b = false;
                
                try { b = res.getBoolean(champ); }
                catch(Exception e) { log.error("Erreur lors de la récupération de " + champ + " : " + e); }
                
                return b;
        }
                
        public boolean IsPresent (String table, String champ, String id, int encrypt) {
                boolean present = false;
                String req = "SELECT * FROM " + table;
                if(id != "") 
                        if(encrypt == 0) req = req + " WHERE " + champ + "='" + id + "'";
                        else req = req + " WHERE AES_DECRYPT(" + champ + ", 'NESPRESSO')='" + id + "'"; 
                try {
                        Statement s = cnx.createStatement();
                        res = s.executeQuery(req);
                        while(res.next()) {
                                present = true;
                        }
                } catch(Exception e) {
                        System.out.println("echec pilote Mysql : "+e);
                }
                return present;
        }
        
        public void Free() {
                try {
                        cnx.close();
                        log.info("Déconnexion de la base de données.");
                } catch (SQLException e) {
                        System.out.println("echec pilote Mysql : "+e);
                        log.error("Erreur lors de la fermeture de la base de données !");
                }
        }
        
        public void UpdateCommande(Commande c) { // Pour mettre à jour le montant total
                float mtotal = 0;
                String req;
                Ligne l;
                Statement s;
                
                l = c.GetLigne1();
                while(l != null) {
                        mtotal = mtotal + l.GetMontant();
                        l = l.GetSuivante();
                }
                req = "UPDATE COMMANDES SET MONTANT=" + mtotal + ", STATUT='" + c.GetStatut() + "' WHERE ID='" + c.GetId() + "'";
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info(req+" ==> montant commande mis à jour");
                        c.SetMontant(mtotal);
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                }
        }
        
        public boolean InsertCommande(Commande c) {
                Statement s;
                String req;
                String id_commande;
                boolean ok = true;
                Ligne l;
                
                // On insère la commande en récupérant son numéro
                Mydate md = new Mydate();
                req = "INSERT INTO COMMANDES VALUES (0,'"+md.Date2My(c.GetDate())+"','"+c.GetStatut()+"','"+c.GetUserresp()+"',"+c.GetMontant()+","+c.GetPort()+")";
                try {
                        s = cnx.createStatement(); s.executeUpdate(req, Statement.RETURN_GENERATED_KEYS);
                        ResultSet cle = s.getGeneratedKeys(); // Pour récupérer l'ID de la ligne insérée
                        int dcle = 1;
                        while (cle.next()) {
                              dcle = cle.getInt(1);
                        }
                        c.SetId(String.format("%05d", dcle));
                        log.info("Commande N° " + c.GetId() + " ajoutée.");
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                        ok = false;
                }
                if(ok) {
                        // On enregistre les lignes qui ont été entrées pour cette nouvelle commande
                        id_commande = c.GetId();
                        l = c.GetLigne1();
                        float tot = 0;
                        while( l != null) {
                                l.SetIdcommande(id_commande);
                                this.InsertLigne(l);
                                tot = tot + l.GetMontant();
                                l = l.GetSuivante();
                        }
                
                        req = "UPDATE COMMANDES SET MONTANT="+tot+" WHERE ID='"+id_commande+"'";
                        try {
                                s = cnx.createStatement(); s.executeUpdate(req);
                                log.info(req+" ==> montant commande mis à jour");
                        } catch(Exception e) {
                                log.error("echec pilote Mysql : "+e);
                                ok = false;
                        }
                        log.info("Création de la commande N° " + id_commande + "complétée avec succès !");
                }
                return ok;
        }
        
        public boolean UpdateLigne(Ligne l) {
                Statement s;
                String req;
                float montant;
                float prix = 0;
                boolean ok = true;
                // On recalcule le montant 
                req = "SELECT PRIX FROM CAPSULES WHERE ID='" + l.GetIdcapsule() + "'";
                try {
                        s = cnx.createStatement(); res = s.executeQuery(req); res.next();
                        prix = res.getFloat("prix");
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                        ok = false;
                }
                
                montant = l.GetNbcapsule() * prix;
                req = "UPDATE LIGNESCDE SET ID_CAPSULE='" + l.GetIdcapsule()+ "', NOMBRE=" + l.GetNbcapsule() + ", MONTANT=" + montant + " WHERE ID='" + l.GetId() + "'";
                try {
                        cnx.createStatement().executeUpdate(req);
                        l.SetMontant(montant);
                        log.info("Requête exécutée : " + req);
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                        ok = false;
                }
        return ok;
        }
        
        public String InsertLigne(Ligne l) {
                Statement s;
                String req;
                float montant;
                float prix = 0;
                String id_ligne = new String();
                
                // On calcule le montant de la ligne
                req = "SELECT PRIX FROM CAPSULES WHERE ID='" + l.GetIdcapsule() + "'";
                try {
                        s = cnx.createStatement(); res = s.executeQuery(req); res.next();
                        prix = res.getFloat("prix");
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                        id_ligne = null;
                }
                montant = l.GetNbcapsule() * prix;
                
                // Insertion dans la base
                req = "INSERT INTO LIGNESCDE VALUES(0,'"+l.GetIdcommande()+"','"+l.GetIduser()+"','"+l.GetIdcapsule()+ "',"+l.GetNbcapsule()+","+montant+")";
                try {
                        s = cnx.createStatement(); s.executeUpdate(req, Statement.RETURN_GENERATED_KEYS);
                        ResultSet cle = s.getGeneratedKeys(); // Pour récupérer l'ID de la ligne insérée
                        int dcle = 1;
                        while (cle.next()) {
                              dcle = cle.getInt(1);
                            }
                        log.info("Requête exécutée : " + req + " => ligne insérée N° "+ dcle);
                        id_ligne = String.format("%05d", dcle);
                        l.SetId(id_ligne);
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                        id_ligne = null;
                }
        return id_ligne;
                
        }
        
        public boolean DeleteLigne(Commande c, String nuligne) {
                Ligne ltmp, ligne;
                boolean ok;
                Statement s;
                String req;
                
                ok = false;
                // D'abord on raccroche la ligne précédente de l avec la suivante de l
                ltmp = c.GetLigne1();
                ligne = null;
                while((!ltmp.GetId().equals(nuligne)) && (ltmp != null)) {
                        ligne = ltmp;
                        ltmp = ltmp.GetSuivante();
                }
                if(ltmp != null) {
                        if(ligne != null) ligne.SetSuivante(ltmp.GetSuivante()); //Ce n'est pas la première ligne de la commande
                        else c.SetLigne1(ltmp.GetSuivante()); // 1ère ligne de la commande
                        req = "DELETE FROM LIGNESCDE WHERE ID='" + nuligne + "'";
                        try {
                                s = cnx.createStatement(); s.executeUpdate(req);
                                log.info("Ligne " + nuligne + " supprim�e.");
                        } catch(Exception e) {
                                log.error("echec pilote Mysql : "+e);
                        }
                } else log.warn("Impossible de supprimer la ligne " + nuligne + " : elle ne se trouve pas dans la commande " + c.GetId());
                return ok;
        }
        
        public boolean InsertUser(User u, String pwd) {
                Statement s;
                boolean ok = false;
                String req = new String("INSERT INTO USERS VALUES(0,'"+u.getNom()+"','"+u.getPrenom()+"','"+u.getRole()+"','"+u.getLogin()+"',AES_ENCRYPT('"+pwd+"','NESPRESSO'),'"+u.getEmail()+"')");
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Création du user réussie !");
                        ok = true;
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                }
                return ok;
        }
        
        public boolean UpdateUser(String id, String param, String valeur) {
                boolean ok = false;
                Statement s;
                String champ = new String(param);
                
                if(param.equals("Prénom")) champ = "PRENOM";
                if(param.equals("Rôle")) champ = "ROLE";
                
                String req = new String("UPDATE USERS SET "+champ+"='"+valeur+"' WHERE ID="+Integer.parseInt(id));
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Mise à jour du user réussie !");
                        ok = true;
                } catch (Exception e) {
                        log.error("Echec pilote Mysql : "+e);
                }               
                return ok;
        }
        
        public boolean DeleteUser(String id) { // Si le user a déjà des commandes, on ne le supprime pas 
        	boolean ok = false;
        	Statement s;
        	
        	String req = new String("SELECT COUNT(*) FROM LIGNESCDE JOIN COMMANDES WHERE COMMANDES.ID=LIGNESCDE.ID_COMMANDE AND (COMMANDES.ID_USER_RESP='"+id+"' OR LIGNESCDE.ID_USER='"+id+"')");
        	try {
        		s = cnx.createStatement(); res = s.executeQuery(req);
        		res.next();
        		if(res.getInt(1) > 0) log.info("Le user "+id+" possède une activité : impossible de le supprimer !");
        		else {
        			log.info("Le user "+id+" n'a pas d'activité : il est possible de le supprimer !");
        			s.executeUpdate("DELETE FROM USERS WHERE ID='"+id+"'");
        			ok = true;
        			log.info("Suppression du user "+id+" réussie !");
        		}
        	} catch(Exception e) {
        		log.info("Erreur lors de la recherche d'un user pour le supprimer : " + e);
        	}
        	return ok;
        }
        
        public boolean InsertCapsule(Capsule cap) {
                Statement s;
                boolean ok = false;
                String req = new String("INSERT INTO CAPSULES VALUES(0,'"+cap.getNom()+"',"+cap.getPrix()+",'"+cap.getImage()+"',"+cap.getForce()+")");
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Création de la capsule réussie !");
                        ok = true;
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                }
                return ok;
        }
        
        public boolean UpdateCapsule(String id, String param, String valeur) {
                boolean ok = false;
                Statement s;
                String champ = new String(param);
                
                String req = new String("UPDATE CAPSULES SET `"+champ+"`='"+valeur+"' WHERE ID='"+id+"'");
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Mise à jour de la capsule réussie !");
                        ok = true;
                } catch (Exception e) {
                        log.error("Echec pilote Mysql : "+e);
                }               
                return ok;
        }
        
        public boolean UpdateCapsule(String id, String param, int valeur) {
            boolean ok = false;
            Statement s;
            String champ = new String(param);
            
            String req = new String("UPDATE CAPSULES SET `"+champ+"`="+valeur+" WHERE ID='"+id+"'");
            try {
                    s = cnx.createStatement(); s.executeUpdate(req);
                    log.info("Mise à jour de la capsule réussie !");
                    ok = true;
            } catch (Exception e) {
                    log.error("Echec pilote Mysql : "+e);
            }               
            return ok;
    }
        
        public boolean UpdateCapsule(String id, String param, float valeur) {
            boolean ok = false;
            Statement s;
            String champ = new String(param);
            
            String req = new String("UPDATE CAPSULES SET `"+champ+"`="+valeur+" WHERE ID='"+id+"'");
            try {
                    s = cnx.createStatement(); s.executeUpdate(req);
                    log.info("Mise à jour de la capsule réussie !");
                    ok = true;
            } catch (Exception e) {
                    log.error("Echec pilote Mysql : "+e);
            }               
            return ok;
    }
        
        public boolean InsertParam(String param, String valeur, boolean cryptage) {
                Statement s;
                boolean ok = false;
                String req = new String("INSERT INTO PARAMETRES VALUES(0,'"+param+"'");
                if(cryptage) req = req + ",AES_ENCRYPT('"+valeur+"','NESPRESSO')','"+ cryptage+"')";
                else req = req + ",'"+valeur+"','"+ cryptage+"')";
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Création du paramètre réussie !");
                        ok = true;
                } catch(Exception e) {
                        log.error("Echec pilote Mysql : "+e);
                }
                return ok;
        }
        
        public boolean UpdateParamNom(String id, String param) {
                Statement s;
                boolean ok = false;
                String req = new String("UPDATE PARAMETRES SET param_name = '"+param+"' WHERE ID='"+id+"'");
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Modification du nom du paramètre rèussie !");
                        ok = true;
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                }
                return ok;
        }       
        
        public boolean UpdateParamValeur(String id, String valeur, boolean crypt) {
                // Il faut d'abord lire la valeur du cryptage avant de mettre à jour
                Statement s;
                boolean ok = false;
                String req = new String();

                if(!crypt) req = "UPDATE PARAMETRES SET param_value = '"+valeur+"' WHERE ID='"+id+"'";
                else req = "UPDATE PARAMETRES SET param_value = AES_ENCRYPT('"+valeur+"', 'NESPRESSO') WHERE ID='"+id+"'";
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Modification de la valeur du paramètre réussie !");
                        ok = true;
                } catch(Exception e) {
                        log.error("Echec pilote Mysql : "+e);
                }
                return ok;
        }
        
        public boolean UpdateParamCrypt(String id, boolean crypt) {
                Statement s;
                boolean ok = false;
                String req = new String("UPDATE PARAMETRES SET param_crypt = "+crypt+" WHERE ID='"+id+"'");
                try {
                        s = cnx.createStatement(); s.executeUpdate(req);
                        log.info("Modification du statut de cryptage du paramètre réussie !");
                        ok = true;
                } catch(Exception e) {
                        log.error("echec pilote Mysql : "+e);
                }
                return ok;
        }
        
        public boolean InsertPaiments(Commande c) {
                Statement s;
                Statement sp;
                boolean ok = false;
                int i = 0;
                String req = new String("SELECT ID_USER, SUM(MONTANT) FROM LIGNESCDE WHERE ID_COMMANDE='" + c.GetId() +"' GROUP BY ID_USER");
                
                try {
                        s = cnx.createStatement(); res = s.executeQuery(req);
                        String iduser = new String();
                        String spai   = new String(); // Statut du paeiment : PAYÉ pour le responsable de la commande, A_PAYER pour les autres
                        while(res.next()) {
                        		iduser = res.getString("ID_USER");
                        		spai = (iduser.equals(c.GetUserresp()) ? "PAYÉ" : "A_PAYER");
                                req = ("INSERT INTO PAIEMENTS VALUES('"+res.getString("ID_USER")+"','"+c.GetId()+"','"+spai+"',"+res.getFloat("SUM(MONTANT)")+")");
                                sp = cnx.createStatement(); sp.executeUpdate(req);
                                i++;
                        }
                        log.info("Création de " + String.valueOf(i) + " paiements avec succès !");
                        ok = true;
                } catch (Exception e) {
                        log.error("Erreur lors de la création des paiments : "+e.getMessage());
                }
                
                
                
                return ok;
        }
        
        public boolean UpdatePaiement(Commande c, User u, String statut) {
        	boolean ok = false;
        	Statement s;
        	
        	String req = new String("UPDATE PAIEMENTS SET STATUT='"+statut+"' WHERE ID_COMMANDE='"+c.GetId()+"' AND ID_USER='"+u.getId()+"'");
        	try {
        		s = cnx.createStatement(); s.executeUpdate(req);
        		log.info("Le paiement du user "+c.GetId()+" pour la commande "+c.GetId()+" a été enregistré avec succès.");
        		ok = true;
        	} catch (Exception e) {
        		log.error("Erreur lors de l'enregistrement d'un réglement : " +e.getMessage());
        	}
        	
        	return ok;
        }
        
        public boolean IsCommandeEnPreparation() {
        	boolean ok = false;
        	
        	String req = new String("SELECT * FROM COMMANDES WHERE STATUT='EN PREPARATION'");
        	try {
                Statement s = cnx.createStatement();
                res = s.executeQuery(req);
                res.last();
                if(res.getRow() > 0 ) { ok = true; }
            }
        	catch(Exception e) {
        		log.error("Erreur lors de la recherche d'une commande en préparation");
        	}
        	
        	
        	return ok;
        }
        
}